#include "bancoAPI.h"

void inicializarBanco() {
   conn = mysql_init(NULL);

   if (!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) {
      fprintf(stderr, "%s\n%s\n", "Erro ao abrir conexao com a base.",mysql_error(conn));
      exit(1);
   }
}

void liberarResultSet(MYSQL_RES *res){
    mysql_free_result(res);
}

void fecharBanco(){
    mysql_close(conn);
}

/*
    Funçao que cria usuario na Base.
*/
void criarUsuario(char* nome, char* senha){
    char sql[256];
    unsigned int rowsEncontradas = 0;

    inicializarBanco();
    
    sprintf(sql,"INSERT INTO usuario VALUES ('%s','%s')", nome, senha);
    printf("%s\n",sql);
    
    /* Enviar a query de consulta do SQL */
    if ( mysql_query(conn, sql) ) {
        fprintf(stderr, "%s\n%s\n", "Erro ao criar usuario. ERRO:",mysql_error(conn));
        fecharBanco();
        exit(1);
    }

    printf("Usuario [%s] criado com sucesso.\n",nome);
    fecharBanco();

}

/*
    Funçao que atualiza usuario na Base.
*/
void atualizarUsuario(char* nome, char* senha){
    char sql[256];
    int rowsAfetadas = 0;

    inicializarBanco();
    
    sprintf(sql,"UPDATE usuario SET senha = '%s' WHERE nome = '%s'", senha, nome);
    printf("%s\n",sql);
    
    /* Enviar a query de consulta do SQL */
    if ( mysql_query(conn, sql) ) {
        fprintf(stderr, "%s\n%s\n", "Erro ao atualizar usuario. ERRO:",mysql_error(conn));
        fecharBanco();
        exit(1);
    }

    rowsAfetadas = mysql_affected_rows(conn);

    if ( rowsAfetadas == 0 ) 
        printf("O Usuario [%s] nao existe em nossas bases.\n",nome);
    else
        printf("Senha Atualizada [%s] atualizado com sucesso.\n",nome);

    fecharBanco();
}

/*
    Funçao que remove usuario na Base e sua respectiva agenda.
*/
void deleteUsuario(char* nome){
    char sql[256];
    int rowsAfetadas = 0;

    inicializarBanco();

    sprintf(sql,"DELETE FROM usuario WHERE nome = '%s'", nome);
    printf("%s\n",sql);
    
    /* Enviar a query de consulta do SQL */
    if ( mysql_query(conn, sql) ) {
        fprintf(stderr, "%s\n%s\n", "Erro ao deletar o usuario. ERRO:",mysql_error(conn));
        fecharBanco();
        exit(1);
    }

    rowsAfetadas = mysql_affected_rows(conn);

    if ( rowsAfetadas == 0 ) 
        printf("O Usuario [%s] nao existe em nossas bases.\n",nome);
    else
        printf("Usuario [%s] e sua Agenda deletada com sucesso.\n",nome);

    fecharBanco();
}

/*
    Funçao para checar o Login.
    Retorna a quantidade de pessoas que foram encontradas no BANCO.
    Se retornar 0, nao foi encontrado ninguem.
*/
int fazerLogin(char* nome, char* senha){
    MYSQL_RES *res;
    MYSQL_ROW row;
    char sql[256];
    int rowsEncontradas = 0;

//    inicializarBanco(); // Motivos de performance =D.
    
    sprintf(sql,"SELECT * FROM usuario WHERE nome = '%s' AND senha = '%s'", nome, senha);
    
    /* Enviar a query de consulta do SQL */
    if (mysql_query(conn, sql)) {
        fprintf(stderr, "%s\n%s\n", "Erro ao fazer busca pelo usuario",mysql_error(conn));
        return -1;
    }

    res = mysql_store_result(conn);

    rowsEncontradas = (int) mysql_num_rows(res);

    liberarResultSet(res);
//    fecharBanco();

    return rowsEncontradas;
}


/* Funçoes de Banco para CRUD */
int recuperarEvento(char* usuario, char* data, char* hora_inicial, MYSQL_RES** resultSet){
    char sql[256];
    
    sprintf(sql,"SELECT %s FROM %s WHERE nome = '%s' AND data = '%s' AND horainicio = '%s'",
                "nome, data, horainicio, horafim, mensagem",
                "agenda",
                usuario, data, hora_inicial);
    
    /* Enviar a query de consulta do SQL */
    if (mysql_query(conn, sql)) {
        fprintf(stderr, "%s\n%s\n", "Erro ao fazer busca pelo usuario",mysql_error(conn));
        return -1;
    }

    (*resultSet) = mysql_store_result(conn);

    return 0;
} 


int recuperarTodosEventos(char* usuario, char* data, MYSQL_RES** resultSet){
    char sql[256];
    
    sprintf(sql,"SELECT %s FROM agenda WHERE nome = '%s' AND data = '%s' ORDER BY horainicio",
                "nome, data, horainicio, horafim, mensagem",
                usuario, data);

    /* Enviar a query de consulta do SQL */
    if (mysql_query(conn, sql)) {
        fprintf(stderr, "%s\n%s\n", "Erro ao fazer busca pelo usuario",mysql_error(conn));
        return -1;
    }

    (*resultSet) = mysql_store_result(conn);

    return 0;
}

void adicionarEvento(Comando* cmd, char* retorno){
	char sql[512];
	char *data_F, *horainicio_F, *horafim_F;
    unsigned int rowsEncontradas = 0;

	MYSQL_RES *res;
    MYSQL_ROW row;

    int logged = 0;

    /* Inicio da rotina de validaçao */
    logged = fazerLogin(cmd->usuario,cmd->senha);

    if ( logged == 0 ){
        strcpy(retorno,"400;Usuario/Senha invalidos");
        return;
    }
    else if ( logged < 0 ){
        strcpy(retorno,"404;Problemas de conexao com o banco.");
        return;
    }
    /* Fim da rotina de validaçao */
	
	compoeData( cmd->data, &data_F );
	compoeHora( cmd->horaI, &horainicio_F );
	compoeHora( cmd->horaF, &horafim_F );

	memset( sql, 0, sizeof( sql ) );

	/* query para verificar se ja existe exatamente o mesmo registro no banco */
	sprintf( sql,"SELECT * FROM agenda WHERE nome = '%s' AND data = '%s' AND horainicio = '%s' AND horafim = '%s' AND mensagem = '%s'\0", 
				cmd->usuario, data_F, horainicio_F, horafim_F, cmd->msg );

	/* Enviar a query de consulta do SQL */
    if (mysql_query(conn, sql)) {
        sprintf(retorno,"404;%s <-> %s",
                "Erro ao buscar entrada da agenda.",
                mysql_error(conn));
        return;
    }

    res = mysql_store_result(conn);

	rowsEncontradas = (int) mysql_num_rows(res);

	if( rowsEncontradas ){
		sprintf(retorno,"400;Ja existe uma entrada na agenda de %s igual a esta", cmd->usuario);
        return;
	}

    liberarResultSet(res);

	memset( sql, 0, sizeof(sql) );

	/* query para verificar se nao ocorre conflito de horas de inicio e fim */
	sprintf( sql,"%s '%s' %s '%s' %s '%s' %s '%s' %s '%s' %s '%s' %s '%s' %s '%s' %s '%s' %s '%s' %s", 
				"SELECT * FROM agenda WHERE nome =",
				cmd->usuario,
				"AND data =", 
				data_F,
				"AND ((horainicio <=", 
				horainicio_F,
				"AND horafim >=",
				horainicio_F,
				") OR (horainicio <=", 
				horafim_F,
				"AND horafim >=",
				horafim_F,
				") OR (horainicio >=",
				horainicio_F, 
				"AND horafim <=",
				horafim_F,
				") OR (horainicio <=",
				horainicio_F, 
				"AND horafim >=",
				horafim_F,
				"))" );

	/* Enviar a query de consulta do SQL */
    if (mysql_query(conn, sql)) {
        sprintf(retorno,"404;%s <-> %s",
                "Erro ao verificar conflito de horarios na agenda.",
                mysql_error(conn));
        return;
    }

    res = mysql_store_result(conn);

	rowsEncontradas = (int) mysql_num_rows(res);

	if( rowsEncontradas ){
        sprintf(retorno, "400;Incompatibilidade de horarios na agenda de %s",cmd->usuario);
		liberarResultSet(res);
        return;
	}

    liberarResultSet(res);

	memset( sql, 0, sizeof( sql ) );

	/* Apos os agendas efetuados, ja podemos inserir o registro na agenda... */	 
    sprintf( sql,"INSERT INTO agenda (nome, data, horainicio, horafim, mensagem) VALUES ('%s', '%s','%s', '%s', '%s')\0", 
		cmd->usuario, data_F, horainicio_F, horafim_F, cmd->msg );
  
    /* Enviar a query de consulta do SQL */
    if ( mysql_query( conn, sql ) ) {
        sprintf(retorno,"404;%s <-> %s",
                "Erro ao inserir registro na agenda.",
                mysql_error(conn));
        return;
    }

    sprintf(retorno, "200;Cadastrado com sucesso");
}

void atualizarEvento(Comando* cmd, char* retorno){
	char sql[512];
	char *data_F, *horainicio_F, *horafim_F;
    unsigned int rowsEncontradas = 0;

	MYSQL_RES *res;
    MYSQL_ROW row;
	
    int logged = 0;

    /* Inicio da rotina de validaçao */
    logged = fazerLogin(cmd->usuario,cmd->senha);

    if ( logged == 0 ){
        strcpy(retorno,"400;Usuario/Senha invalidos");
        return;
    }
    else if ( logged < 0 ){
        strcpy(retorno,"404;Problemas de conexao com o banco.");
        return;
    }
    /* Fim da rotina de validaçao */

	compoeData( cmd->data, &data_F );
	compoeHora( cmd->horaI, &horainicio_F );
	compoeHora( cmd->horaF, &horafim_F );

	memset( sql, 0, sizeof( sql ) );

	/* query para verificar se ja existe exatamente o mesmo registro no banco */
	sprintf( sql,"SELECT * FROM agenda WHERE nome = '%s' AND data = '%s' AND horainicio = '%s' AND horafim = '%s' AND mensagem = '%s'\0", 
				cmd->usuario, data_F, horainicio_F, horafim_F, cmd->msg );

	/* Enviar a query de consulta do SQL */
    if (mysql_query(conn, sql)) {
        sprintf(retorno,"404;%s <-> %s",
                "Erro ao verificar entrada da agenda.",
                mysql_error(conn));
        return;
    }

    res = mysql_store_result(conn);

	rowsEncontradas = (int) mysql_num_rows(res);

	if( rowsEncontradas ){
        sprintf(retorno, "400;Nao ha o que alterar. Pois, hora de termino e a Mensagem sao iguais");
		liberarResultSet(res);
        return;
	}

    liberarResultSet(res);

	memset( sql, 0, sizeof(sql) );

	/* query para verificar casos em que a nova hora final intercepta algum evento posterior*/
	sprintf( sql,"%s '%s'%s '%s' %s '%s' %s '%s'", 
				"SELECT * FROM agenda WHERE nome =",
				cmd->usuario,
				"AND data =", 
				data_F,
				"AND horainicio >=",
				horainicio_F,
				"AND horainicio <=",
				horafim_F);

	/* Enviar a query de consulta do SQL */
    if (mysql_query(conn, sql)) {
        sprintf(retorno,"404;%s <-> %s",
                "Erro ao validar horarios da agenda.",
                mysql_error(conn));
        return;
    }

    res = mysql_store_result(conn);
	rowsEncontradas = (int) mysql_num_rows(res);

	if( rowsEncontradas > 1 ){ // putz, o evento invadiu outro!
		sprintf(retorno, "404;Incompatibilidade de horario entre eventos");
		liberarResultSet(res);
        return;
	}
	
	// entao veremos se ha algum registro habilitado a ser atualizado

	liberarResultSet(res);

	memset( sql, 0, sizeof(sql) );

	/* query para verificar se ocorre caso em que se pode atualizar hora final*/
	sprintf( sql,"%s '%s'%s '%s' %s '%s'", 
			"SELECT * FROM agenda WHERE nome =",
			cmd->usuario,
			"AND data =", 
			data_F,
			"AND horainicio =",
			horainicio_F);

	/* Enviar a query de consulta do SQL */
    if (mysql_query(conn, sql)) {
        sprintf(retorno,"404;%s <-> %s",
                "Erro ao verificar registros habilitados a atualizacao da agenda.",
                mysql_error(conn));
        return;
    }

    res = mysql_store_result(conn);

	rowsEncontradas = (int) mysql_num_rows(res);

	if( !rowsEncontradas ){
        sprintf(retorno, "404;Entrada nao encontrada em sua Agenda");
		liberarResultSet(res);
        return;
	}

    liberarResultSet(res);

	memset( sql, 0, sizeof( sql ) );

	/* Apos os agendas efetuados, ja podemos atualizar o registro na agenda... */	     
	sprintf( sql,"UPDATE agenda SET horafim = '%s', mensagem = '%s' WHERE nome = '%s' AND data = '%s' AND horainicio = '%s'", 
			horafim_F, cmd->msg, cmd->usuario, data_F, horainicio_F );
  
    /* Enviar a query de consulta do SQL */
    if ( mysql_query( conn, sql ) ) {
        sprintf(retorno,"404;%s <-> %s",
                "Erro ao atualizar entrada da agenda.",
                mysql_error(conn));
        return;
    }

    sprintf(retorno, "200;Entrada Alterada com Sucesso");
}

void removerEvento(Comando* cmd, char* retorno){
    char sql[256];
    int logged = 0;
    int rowsAfetadas = 0;
    char *T_data, *T_horaI;


    /* Inicio da rotina de validaçao */
    logged = fazerLogin(cmd->usuario,cmd->senha);

    if ( logged == 0 ){
        strcpy(retorno,"400;Usuario/Senha invalidos");
        return;
    }
    else if ( logged < 0 ){
        strcpy(retorno,"404;Problemas de conexao com o banco.");
        return;
    }
    /* Fim da rotina de validaçao */

    compoeData( cmd->data , &T_data);
    compoeHora( cmd->horaI, &T_horaI);
    sprintf(sql,"DELETE FROM agenda WHERE nome = '%s' AND data = '%s' AND horainicio = '%s'",
            cmd->usuario,T_data,T_horaI );

//    printf("%s\n",sql);
    
    /* Enviar a query de consulta do SQL */
    if ( mysql_query(conn, sql) ) {
        sprintf(retorno,"404;%s <-> %s",
                "Erro ao deletar entrada da agenda.",
                mysql_error(conn));
        return;
    }

    rowsAfetadas = mysql_affected_rows(conn);

    if ( rowsAfetadas == 0 )
        sprintf(retorno,"400;O evento solicitado nao foi encontrado para ser removido :/");
    else
        sprintf(retorno,"200;Evento removido com sucesso. \\o/");

}

void removerTodosEventos(Comando* cmd, char* retorno){
    char sql[256];
    int logged = 0;
    int rowsAfetadas = 0;
    char *T_data, *T_horaI;

    /* Inicio da rotina de validaçao */
    logged = fazerLogin(cmd->usuario,cmd->senha);

    if ( logged == 0 ){
        strcpy(retorno,"400;Usuario/Senha invalidos");
        return;
    }
    else if ( logged < 0 ){
        strcpy(retorno,"404;Problemas de conexao com o banco.");
        return;
    }
    /* Fim da rotina de validaçao */

    compoeData( cmd->data , &T_data);
    sprintf(sql,"DELETE FROM agenda WHERE nome = '%s' AND data = '%s'",
            cmd->usuario,T_data);

//    printf("%s\n",sql);
    
    /* Enviar a query de consulta do SQL */
    if ( mysql_query(conn, sql) ) {
        sprintf(retorno,"404;%s <-> %s",
                "Erro ao deletar entrada da agenda.",
                mysql_error(conn));
        return;
    }

    rowsAfetadas = mysql_affected_rows(conn);

    if ( rowsAfetadas == 0 )
        sprintf(retorno,"400;O data solicitada nao possui nenhum evento.");
    else
        sprintf(retorno,"200;Foram removidos <%d> eventos com sucesso. \\o/", rowsAfetadas);
}

